package com.zws.cucumber.plugin.procedure;

import io.cucumber.core.eventbus.EventBus;
import io.cucumber.core.plugin.PrettyFormatter;
import io.cucumber.plugin.event.EventHandler;
import io.cucumber.plugin.event.TestStepFinished;
import org.springframework.util.ReflectionUtils;

import java.io.BufferedOutputStream;
import java.lang.reflect.Method;
import java.time.Instant;
import java.util.UUID;

public class ZwsProcedureEventBus implements EventBus {

    private static PrettyFormatter prettyFormatter = new PrettyFormatter(new BufferedOutputStream(System.out));

    private EventBus parent;
    private Throwable error;

    public ZwsProcedureEventBus(EventBus parent) {
        this.parent = parent;
    }

    public Throwable getError() {
        return error;
    }

    @Override
    public Instant getInstant() {
        return parent.getInstant();
    }

    @Override
    public UUID generateId() {
        return parent.generateId();
    }

    @Override
    public <T> void send(T event) {
        if (event instanceof TestStepFinished) {
            printTestStepFinishedEvent(((TestStepFinished) event));
            Throwable error = ((TestStepFinished) event).getResult().getError();
            if (error != null && this.error == null) {
                this.error = error;
            }
        }
    }

    @Override
    public <T> void sendAll(Iterable<T> queue) {

    }

    @Override
    public <T> void registerHandlerFor(Class<T> eventType, EventHandler<T> handler) {
        parent.registerHandlerFor(eventType, handler);
    }

    @Override
    public <T> void removeHandlerFor(Class<T> eventType, EventHandler<T> handler) {
        parent.removeHandlerFor(eventType, handler);
    }

    private void printTestStepFinishedEvent(TestStepFinished event) {
        try {
            Method method = ReflectionUtils.findMethod(PrettyFormatter.class, "printStep", TestStepFinished.class);
            method.setAccessible(true);
            method.invoke(prettyFormatter, event);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
